/**
 * PDF Service
 * Handles generation of PDFs from research results
 */

/**
 * Generate a PDF from the research content
 * @param {string|any} title - The research title/query
 * @param {string|any} content - The markdown content of the research
 * @param {Object} metadata - Additional metadata for the PDF
 * @returns {Promise<Blob>} A promise resolving to the generated PDF blob
 */
async function generatePdf(title, content, metadata = {}) {
    // Check if necessary libraries are loaded
    if (typeof jspdf === 'undefined') {
        throw new Error('PDF generation libraries not loaded (jsPDF missing)');
    }

    if (typeof html2canvas === 'undefined') {
        throw new Error('PDF generation libraries not loaded (html2canvas missing)');
    }

    // Ensure title and content are strings
    title = String(title || 'Research Report');
    content = String(content || '');

    // Create a temporary container to render the markdown
    const tempContainer = document.createElement('div');
    tempContainer.style.position = 'absolute';
    tempContainer.style.left = '-9999px';
    tempContainer.style.top = '-9999px';
    tempContainer.style.width = '8.5in'; // US Letter width
    tempContainer.className = 'pdf-content';

    // Add PDF-specific styles
    tempContainer.innerHTML = `
        <style>
            .pdf-content {
                font-family: Arial, sans-serif;
                color: #333;
                line-height: 1.5;
                padding: 20px;
                background-color: #ffffff;
            }
            .pdf-content h1 {
                font-size: 24px;
                color: #000;
                margin-bottom: 12px;
            }
            .pdf-content h2 {
                font-size: 20px;
                color: #000;
                margin-top: 20px;
                margin-bottom: 10px;
            }
            .pdf-content h3 {
                font-size: 16px;
                color: #000;
                margin-top: 16px;
                margin-bottom: 8px;
            }
            .pdf-content p {
                margin-bottom: 10px;
            }
            .pdf-content ul, .pdf-content ol {
                margin-left: 20px;
                margin-bottom: 10px;
            }
            .pdf-content li {
                margin-bottom: 5px;
            }
            .pdf-content pre {
                background-color: #f5f5f5;
                padding: 10px;
                border-radius: 4px;
                overflow-x: auto;
                font-family: monospace;
                font-size: 12px;
                margin-bottom: 10px;
            }
            .pdf-content code {
                font-family: monospace;
                background-color: #f5f5f5;
                padding: 2px 4px;
                border-radius: 2px;
                font-size: 12px;
            }
            .pdf-content blockquote {
                border-left: 4px solid #ddd;
                padding-left: 15px;
                margin-left: 0;
                color: #666;
            }
            .pdf-content table {
                border-collapse: collapse;
                width: 100%;
                margin-bottom: 15px;
            }
            .pdf-content table, .pdf-content th, .pdf-content td {
                border: 1px solid #ddd;
            }
            .pdf-content th, .pdf-content td {
                padding: 8px;
                text-align: left;
            }
            .pdf-content th {
                background-color: #f5f5f5;
            }
            .pdf-metadata {
                color: #666;
                font-size: 12px;
                margin-bottom: 20px;
                border-bottom: 1px solid #ddd;
                padding-bottom: 10px;
            }
            .pdf-header {
                text-align: center;
                border-bottom: 2px solid #333;
                padding-bottom: 10px;
                margin-bottom: 20px;
            }
            .pdf-footer {
                border-top: 1px solid #ddd;
                padding-top: 10px;
                margin-top: 20px;
                font-size: 12px;
                color: #666;
            }
        </style>
        <div class="pdf-header">
            <h1>${title}</h1>
        </div>
        <div class="pdf-metadata">
            <p>Generated: ${new Date().toLocaleString()}</p>
            ${metadata.mode ? `<p>Mode: ${metadata.mode}</p>` : ''}
            ${metadata.iterations ? `<p>Search iterations: ${metadata.iterations}</p>` : ''}
            ${metadata.id ? `<p>Research ID: ${metadata.id}</p>` : ''}
            ${metadata.timestamp ? `<p>Research Date: ${new Date(metadata.timestamp).toLocaleString()}</p>` : ''}
        </div>
        <div class="pdf-body">
            ${window.marked ? window.marked.parse(content) : content}
        </div>
        <div class="pdf-footer">
            <p>Generated by Deep Research System</p>
        </div>
    `;

    // Add to the document body temporarily
    document.body.appendChild(tempContainer);

    try {
        console.log("Starting PDF generation...");

        // Use the jsPDF library from the window object
        const { jsPDF } = window.jspdf;

        // Create a new PDF document
        const pdf = new jsPDF('p', 'pt', 'letter');
        const pdfWidth = pdf.internal.pageSize.getWidth();
        const pdfHeight = pdf.internal.pageSize.getHeight();
        const margin = 40;
        const contentWidth = pdfWidth - 2 * margin;

        // Function to add page with header
        const addPageWithHeader = (pageNum) => {
            if (pageNum > 1) {
                pdf.addPage();
            }
            pdf.setFontSize(8);
            pdf.setTextColor(100, 100, 100);
            pdf.text(`Deep Research - ${title} - Page ${pageNum}`, margin, pdfHeight - 20);
        };

        // Process each element with a more optimized approach
        const contentDiv = tempContainer.querySelector('.pdf-body');
        if (!contentDiv) {
            throw new Error('PDF body container not found');
        }

        // Create a more efficient PDF generation approach that keeps text selectable
        const elements = Array.from(contentDiv.children);
        let currentY = margin;
        let pageNum = 1;

        // Add the first page with header
        addPageWithHeader(pageNum);

        // Process each element
        for (const element of elements) {
            // Skip style element
            if (element.tagName === 'STYLE') continue;

            try {
                // Simple text content - handled directly by jsPDF for better text selection
                if ((element.tagName === 'P' || element.tagName === 'DIV' || element.tagName === 'H1' ||
                     element.tagName === 'H2' || element.tagName === 'H3') &&
                    !element.querySelector('img, canvas, svg, table') &&
                    !element.innerHTML.includes('<')) {

                    pdf.setFont('helvetica', element.tagName.startsWith('H') ? 'bold' : 'normal');
                    pdf.setFontSize(element.tagName === 'H1' ? 18 : (element.tagName === 'H2' ? 16 : (element.tagName === 'H3' ? 14 : 11)));
                    pdf.setTextColor(0, 0, 0);

                    const text = element.textContent.trim();
                    if (!text) continue; // Skip empty text

                    const textLines = pdf.splitTextToSize(text, contentWidth);

                    // Check if we need a new page
                    if (currentY + (textLines.length * 14) > pdfHeight - margin) {
                        pageNum++;
                        addPageWithHeader(pageNum);
                        currentY = margin;
                    }

                    pdf.text(textLines, margin, currentY + 12);
                    currentY += (textLines.length * 14) + 10;
                }
                // List elements - handle bullets and numbering
                else if (element.tagName === 'UL' || element.tagName === 'OL') {
                    const listItems = Array.from(element.querySelectorAll('li'));
                    for (let i = 0; i < listItems.length; i++) {
                        const item = listItems[i];
                        const itemText = item.textContent.trim();
                        if (!itemText) continue;

                        pdf.setFont('helvetica', 'normal');
                        pdf.setFontSize(11);
                        pdf.setTextColor(0, 0, 0);

                        const bulletPoint = element.tagName === 'UL' ? '•' : `${i + 1}.`;
                        const textWithBullet = `${bulletPoint} ${itemText}`;
                        const textLines = pdf.splitTextToSize(textWithBullet, contentWidth - 10);

                        // Check if we need a new page
                        if (currentY + (textLines.length * 14) > pdfHeight - margin) {
                            pageNum++;
                            addPageWithHeader(pageNum);
                            currentY = margin;
                        }

                        pdf.text(textLines, margin, currentY + 12);
                        currentY += (textLines.length * 14) + 5;
                    }
                    currentY += 5; // Add some space after the list
                }
                // Tables - render with proper cells
                else if (element.tagName === 'TABLE') {
                    const rows = Array.from(element.querySelectorAll('tr'));
                    if (rows.length === 0) continue;

                    // Get header cells
                    const headerCells = Array.from(rows[0].querySelectorAll('th, td'));
                    const colCount = headerCells.length || 1;
                    const colWidth = contentWidth / colCount;

                    // Start table at current position
                    let tableY = currentY;

                    // Check if we need a new page
                    if (tableY + 20 > pdfHeight - margin) {
                        pageNum++;
                        addPageWithHeader(pageNum);
                        tableY = margin;
                    }

                    // Draw header background
                    pdf.setFillColor(240, 240, 240);
                    pdf.rect(margin, tableY, contentWidth, 20, 'F');

                    // Draw header text
                    pdf.setFont("helvetica", "bold");
                    pdf.setFontSize(10);
                    pdf.setTextColor(0, 0, 0);

                    headerCells.forEach((cell, index) => {
                        const text = cell.textContent.trim();
                        const x = margin + (index * colWidth) + 5;
                        pdf.text(text, x, tableY + 13);
                    });

                    // Draw horizontal line after header
                    pdf.setDrawColor(200, 200, 200);
                    pdf.setLineWidth(0.5);
                    pdf.line(margin, tableY + 20, margin + contentWidth, tableY + 20);

                    tableY += 20;

                    // Draw table rows
                    pdf.setFont("helvetica", "normal");
                    for (let i = 1; i < rows.length; i++) {
                        // Check if we need a new page
                        if (tableY + 20 > pdfHeight - margin) {
                            pageNum++;
                            addPageWithHeader(pageNum);
                            tableY = margin;

                            // Redraw header on new page
                            pdf.setFillColor(240, 240, 240);
                            pdf.rect(margin, tableY, contentWidth, 20, 'F');

                            pdf.setFont("helvetica", "bold");
                            headerCells.forEach((cell, index) => {
                                const text = cell.textContent.trim();
                                const x = margin + (index * colWidth) + 5;
                                pdf.text(text, x, tableY + 13);
                            });

                            pdf.line(margin, tableY + 20, margin + contentWidth, tableY + 20);
                            tableY += 20;
                            pdf.setFont("helvetica", "normal");
                        }

                        // Get cells for this row
                        const cells = Array.from(rows[i].querySelectorAll('td, th'));

                        // Draw cell content
                        cells.forEach((cell, index) => {
                            const text = cell.textContent.trim();
                            if (!text) return;

                            const x = margin + (index * colWidth) + 5;
                            pdf.text(text, x, tableY + 13);
                        });

                        // Draw horizontal line after row
                        pdf.line(margin, tableY + 20, margin + contentWidth, tableY + 20);
                        tableY += 20;
                    }

                    // Draw vertical lines
                    for (let i = 0; i <= colCount; i++) {
                        const x = margin + (i * colWidth);
                        pdf.line(x, currentY, x, tableY);
                    }

                    // Update current position to after the table
                    currentY = tableY + 10;
                }
                // Code blocks - render with monospace font and background
                else if (element.tagName === 'PRE' || element.querySelector('pre')) {
                    const preElement = element.tagName === 'PRE' ? element : element.querySelector('pre');
                    const codeText = preElement.textContent.trim();
                    if (!codeText) continue;

                    pdf.setFont("courier", "normal"); // Use monospace font for code
                    pdf.setFontSize(9);
                    pdf.setTextColor(0, 0, 0);

                    // Split code into lines, respecting line breaks
                    const codeLines = codeText.split(/\r?\n/);
                    const wrappedLines = [];

                    codeLines.forEach(line => {
                        // Wrap long lines
                        const wrappedLine = pdf.splitTextToSize(line, contentWidth - 20);
                        wrappedLines.push(...wrappedLine);
                    });

                    // Calculate code block height
                    const lineHeight = 12;
                    const codeHeight = wrappedLines.length * lineHeight + 20; // 10px padding top and bottom

                    // Check if we need a new page
                    if (currentY + codeHeight > pdfHeight - margin) {
                        pageNum++;
                        addPageWithHeader(pageNum);
                        currentY = margin;
                    }

                    // Draw code block background
                    pdf.setFillColor(245, 245, 245);
                    pdf.rect(margin, currentY, contentWidth, codeHeight, 'F');

                    // Draw code content
                    pdf.setTextColor(0, 0, 0);
                    wrappedLines.forEach((line, index) => {
                        pdf.text(line, margin + 10, currentY + 15 + (index * lineHeight));
                    });

                    // Update position
                    currentY += codeHeight + 10;
                }
                // Images - render as images
                else if (element.tagName === 'IMG' || element.querySelector('img')) {
                    const imgElement = element.tagName === 'IMG' ? element : element.querySelector('img');

                    if (!imgElement || !imgElement.src) continue;

                    try {
                        // Create a new image to get dimensions
                        const img = new Image();
                        img.src = imgElement.src;

                        // Calculate dimensions
                        const imgWidth = contentWidth;
                        const imgHeight = img.height * (contentWidth / img.width);

                        // Check if we need a new page
                        if (currentY + imgHeight > pdfHeight - margin) {
                            pageNum++;
                            addPageWithHeader(pageNum);
                            currentY = margin;
                        }

                        // Add image to PDF
                        pdf.addImage(img.src, 'JPEG', margin, currentY, imgWidth, imgHeight);
                        currentY += imgHeight + 10;
                    } catch (imgError) {
                        console.error('Error adding image:', imgError);
                        pdf.text("[Image could not be rendered]", margin, currentY + 12);
                        currentY += 20;
                    }
                }
                // Fallback for moderately complex elements - try to extract text first before using canvas
                else {
                    // Try to extract text content and render it directly first
                    const textContent = element.textContent.trim();

                    if (textContent) {
                        pdf.setFont('helvetica', 'normal');
                        pdf.setFontSize(11);
                        pdf.setTextColor(0, 0, 0);

                        const textLines = pdf.splitTextToSize(textContent, contentWidth);

                        // Check if we need a new page
                        if (currentY + (textLines.length * 14) > pdfHeight - margin) {
                            pageNum++;
                            addPageWithHeader(pageNum);
                            currentY = margin;
                        }

                        pdf.text(textLines, margin, currentY + 12);
                        currentY += (textLines.length * 14) + 10;
                    } else {
                        // Only use html2canvas as a last resort for elements with no text content
                        try {
                            const canvas = await html2canvas(element, {
                                scale: 2,
                                useCORS: true,
                                logging: false,
                                backgroundColor: '#FFFFFF'
                            });

                            const imgData = canvas.toDataURL('image/png');
                            const imgWidth = contentWidth;
                            const imgHeight = (canvas.height * contentWidth) / canvas.width;

                            if (currentY + imgHeight > pdfHeight - margin) {
                                pageNum++;
                                addPageWithHeader(pageNum);
                                currentY = margin;
                            }

                            pdf.addImage(imgData, 'PNG', margin, currentY, imgWidth, imgHeight);
                            currentY += imgHeight + 10;
                        } catch (canvasError) {
                            console.error('Error rendering complex element:', canvasError);
                            pdf.text("[Content could not be rendered]", margin, currentY + 12);
                            currentY += 20;
                        }
                    }
                }
            } catch (elementError) {
                console.error('Error processing element:', elementError);
                pdf.text("[Error rendering content]", margin, currentY + 12);
                currentY += 20;
            }
        }

        // Generate the PDF blob
        const blob = pdf.output('blob');
        console.log("PDF generation completed successfully");
        return blob;
    } catch (error) {
        console.error('Error in PDF generation:', error);
        throw error;
    } finally {
        // Clean up
        if (document.body.contains(tempContainer)) {
            document.body.removeChild(tempContainer);
        }
    }
}

/**
 * Generate and download a PDF from research content
 * @param {Object|string} titleOrData - Either the research title or the entire research data object
 * @param {string|null} content - The markdown content of the research, or research ID if first param is data object
 * @param {Object} metadata - Additional metadata for the PDF
 * @returns {Promise<void>} A promise that resolves when the PDF has been downloaded
 */
async function downloadPdf(titleOrData, content, metadata = {}) {
    try {
        console.log("Starting PDF download process...");

        let title, pdfContent, pdfMetadata;

        // Determine if we're being passed a research data object or direct parameters
        if (typeof titleOrData === 'object' && titleOrData !== null) {
            // We were passed a research data object
            const researchData = titleOrData;
            const researchId = content; // Second parameter is research ID in this case

            console.log("Processing research data object", { researchId });

            // Extract title from research data
            title = researchData.query || researchData.title || researchData.prompt || `Research ${researchId}`;

            // Extract content - try all possible locations based on how data might be structured
            if (researchData.markdown) {
                pdfContent = researchData.markdown;
            } else if (researchData.content) {
                pdfContent = researchData.content;
            } else if (researchData.text) {
                pdfContent = researchData.text;
            } else if (researchData.summary) {
                pdfContent = researchData.summary;
            } else if (researchData.results && Array.isArray(researchData.results)) {
                pdfContent = researchData.results.join('\n\n');
            } else if (researchData.report) {
                pdfContent = researchData.report;
            } else if (researchData.research && researchData.research.content) {
                pdfContent = researchData.research.content;
            } else if (researchData.html) {
                // If we have HTML, convert it to a reasonable markdown-like format
                pdfContent = researchData.html
                    .replace(/<h1[^>]*>(.*?)<\/h1>/gi, '# $1\n\n')
                    .replace(/<h2[^>]*>(.*?)<\/h2>/gi, '## $1\n\n')
                    .replace(/<h3[^>]*>(.*?)<\/h3>/gi, '### $1\n\n')
                    .replace(/<p[^>]*>(.*?)<\/p>/gi, '$1\n\n')
                    .replace(/<li[^>]*>(.*?)<\/li>/gi, '- $1\n')
                    .replace(/<br\s*\/?>/gi, '\n')
                    .replace(/<(?:.|\n)*?>/gm, '') // Remove remaining HTML tags
                    .replace(/&nbsp;/gi, ' ')
                    .replace(/&lt;/gi, '<')
                    .replace(/&gt;/gi, '>')
                    .replace(/&amp;/gi, '&')
                    .replace(/&quot;/gi, '"')
                    .replace(/&apos;/gi, "'")
                    .replace(/\n{3,}/g, '\n\n'); // Normalize excessive newlines
            } else {
                // Last resort: stringify the entire object
                console.warn("Could not find content in research data, using JSON stringification");
                pdfContent = JSON.stringify(researchData, null, 2);
            }

            // Extract metadata
            pdfMetadata = {
                mode: researchData.mode,
                iterations: researchData.iterations,
                timestamp: researchData.timestamp || researchData.created_at || new Date().toISOString(),
                id: researchId
            };
        } else {
            // We were passed direct parameters
            title = titleOrData || 'Research Report';
            pdfContent = content || '';
            pdfMetadata = metadata || {};
        }

        // Ensure title is a string
        title = String(title || 'Research Report');

        console.log("PDF parameters prepared", { titleLength: title.length, contentLength: pdfContent?.length });

        // Show loading indicator
        const loadingIndicator = document.createElement('div');
        loadingIndicator.className = 'loading-indicator';
        loadingIndicator.innerHTML = '<div class="spinner"></div><div>Generating PDF...</div>';
        loadingIndicator.style.position = 'fixed';
        loadingIndicator.style.top = '50%';
        loadingIndicator.style.left = '50%';
        loadingIndicator.style.transform = 'translate(-50%, -50%)';
        loadingIndicator.style.zIndex = '9999';
        loadingIndicator.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        loadingIndicator.style.color = 'white';
        loadingIndicator.style.padding = '20px';
        loadingIndicator.style.borderRadius = '5px';
        document.body.appendChild(loadingIndicator);

        // Generate the PDF
        const blob = await generatePdf(title, pdfContent, pdfMetadata);

        // Create a download link
        const url = URL.createObjectURL(blob);
        const downloadLink = document.createElement('a');
        downloadLink.href = url;

        // Generate a filename based on the title
        const safeTitle = title.replace(/[^a-z0-9]/gi, '_').toLowerCase().substring(0, 30);
        downloadLink.download = `${safeTitle}_research.pdf`;

        // Trigger the download
        document.body.appendChild(downloadLink);
        downloadLink.click();

        // Clean up
        document.body.removeChild(downloadLink);
        URL.revokeObjectURL(url);

        console.log("PDF download process completed");
        return true;
    } catch (error) {
        console.error('Error generating PDF:', error);
        alert('Error generating PDF: ' + (error.message || 'Unknown error'));
        throw error;
    } finally {
        // Remove loading indicator
        const loadingIndicator = document.querySelector('.loading-indicator');
        if (loadingIndicator) {
            document.body.removeChild(loadingIndicator);
        }
    }
}

// Export PDF functions
window.pdfService = {
    generatePdf,
    downloadPdf
};
